package com.springcloud.zuul.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.springcloud.zuul.common.constant.Constant;
import com.springcloud.zuul.common.constant.ServiceCode;
import com.springcloud.zuul.common.exception.RRException;
import com.springcloud.zuul.common.utlis.*;
import com.springcloud.zuul.common.validator.ValidatorUtils;
import com.springcloud.zuul.common.validator.group.UpdateGroup;
import com.springcloud.zuul.entity.SysDeptEntity;
import com.springcloud.zuul.entity.SysRoleEntity;
import com.springcloud.zuul.entity.SysUserEntity;
import com.springcloud.zuul.exception.ServiceException;
import com.springcloud.zuul.form.userForm;
import com.springcloud.zuul.mapper.SysUserDao;
import com.springcloud.zuul.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * 系统用户
 */
@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {

    @Autowired
    private SysUserRoleService sysUserRoleService;
    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private ComUtils comUtils;

    @Autowired
    SysDeptService sysDeptService;

    @Autowired
    SysMenuService sysMenuService;

    @Autowired
    SysRoleMenuService sysRoleMenuService;

    @Override
    public IPage queryPage(Map<String, Object> params) {
        String userName = (String) params.get("userName");
        Long insby = (Long) params.get("insby");

        IPage<SysUserEntity> page = this.page(
                new Query<SysUserEntity>().getPage(params),
                new QueryWrapper<SysUserEntity>()
                        .like(StringUtils.isNotBlank(userName), "user_name", userName)
                        .eq(insby != null, "insby", insby)
        );
        //循环处理
        List<SysUserEntity>userEntities=page.getRecords();
        for(SysUserEntity userEntity:userEntities){
            //如果公司编码不为空。那就拿公司编码去获取公司信息
            if(StringUtils.isNotEmpty(userEntity.getDeptId())){
                SysDeptEntity deptEntity=sysDeptService.queryByDeptId(userEntity.getDeptId());
                if(Objects.nonNull(deptEntity)){
                    userEntity.setDeptName(deptEntity.getDeptName());
                }
            }
        }
        //然后存在set回去
        page.setRecords(userEntities);

        return page;
    }

    @Override
    public List<String> queryAllPerms(String userId,String productId) {
        return baseMapper.queryAllPerms(userId,productId);
    }

    /**
     * Description:查询用户的所有菜单ID
     *
     * @param userId
     * @return java.util.List<java.lang.String>
     * @author zhlu
     * @date 2019/12/28 2:02 下午
     */
    @Override
    public List<String> queryAllMenuId(String userId,String productId) {
        return baseMapper.queryAllMenuId(userId,productId);
    }

    @Override
    public SysUserEntity queryByUserName(String username) {
        return baseMapper.queryByUserName(username);
    }

    @Override
    public SysUserEntity queryByPhone(String phone) {
        return baseMapper.queryByPhone(phone);
    }

    /**
     * Description:根据用户编码获取用户资料
     *
     * @param userId
     * @return com.springcloud.zuul.entity.SysUserEntity
     * @author zhlu
     * @date 2020/1/2 3:15 下午
     */
    @Override
    public SysUserEntity queryByUserId(String userId) {
        return baseMapper.queryByUserId(userId);
    }

    /**
     * Description:保存用户
     *
     * @param user
     * @return com.springcloud.zuul.common.utlis.JsonResult
     * @author zhlu
     * @date 2019/12/27 11:57 上午
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult saveUser(SysUserEntity user) {

        userForm userForm = new userForm();
        //验证参数是否正确
        verifyForm(user);
        //是否特殊登陆账号    0.否   1.是
        //手机注册或者邮箱注册,会分配默认的资料
        if (Constant.NON_SPECIAL == user.getNonSpecial()) {
            //特殊账号登陆账号
            user.setLoginName(user.getNo());
            //特殊账号登陆密码
            user.setPassword(RandomStringUtils.random(6, Constant.LOWER_CASE_LETTERS));
            //初始密码，只是第一次创建之后返回
            userForm.setPassword(user.getPassword());
            //密码
            user.setPassword(new Sha256Hash(user.getPassword(), user.getSalt()).toHex());
            user.setUserName(Constant.MOBILE_PHONE_USERS + user.getNo());
        } else {
            //初始密码，只是第一次创建之后返回
            userForm.setPassword(user.getPassword());
            user.setPassword(new Sha256Hash(user.getPassword(), user.getSalt()).toHex());
        }
        //Mac地址
        user.setMacAddress(MacUtils.getWindowsMACAddress());
        //创建时间
        user.setInstm(ConvertDateTime.getCurrentTime());
        //执行方法
        user.setInsfnc(this.getClass().getSimpleName() + "." + Thread.currentThread().getStackTrace()[1].getMethodName());

        //完整性验证
        ValidatorUtils.validateEntity(user, UpdateGroup.class);
        //手机号已存在
        if (baseMapper.countByPhone(user.getPhone()) > 0) {
            throw new ServiceException(ServiceCode.PRESENCE_USER);
        }
        ;

        this.save(user);

        userForm.setLoginName(user.getLoginName());
        userForm.setNo(user.getNo());
        userForm.setUserName(user.getUserName());
        userForm.setEmail(user.getEmail());
        userForm.setPhone(user.getPhone());
//		//检查角色是否越权
//		checkRole(user);
//
//		//保存用户与角色关系
//		sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());

        return JsonResult.success(userForm, ServiceCode.NEW_USER_SUCCESS);
    }

    /**
     * Description:验证参数是否正确
     *
     * @param user
     * @return void
     * @author zhlu
     * @date 2020/1/7 12:01 下午
     */
    private void verifyForm(SysUserEntity user) {
        String userId;
        //用户类型 0.公司用户 1.个人用户
        //公司用户
        if (Constant.USER_TYPE == user.getUserType()) {
            userId = comUtils.getLocalTrmSeqNumByLook("com_user", "security", "sys_user", "user_id");
            //公司用户，所属公司不能为空！
            if (StringUtils.isEmpty(user.getDeptId())) {
                throw new ServiceException(ServiceCode.COMPANY_USERS);
            }
            //不存在当前公司
            if (StringUtils.isNotEmpty(user.getDeptId())
                    && Objects.isNull(sysDeptService.queryByDeptId(user.getDeptId()))) {
                throw new ServiceException(ServiceCode.NO_CURRENT_COMPANY_EXISTS);
            }
            //检查公司与选择产品的权限干嘛是否越权
            checkDeptAndProdu(user);
        } else {
            userId = comUtils.getLocalTrmSeqNumByLook("each_user", "security", "sys_user", "user_id");
			//检查选择产品的权限范围是否越权
            checkProdu(user);
        }
        //检查角色是否越权
        checkRole(user);
        //自定义UUID
        String stream = userId.substring(userId.substring(0, userId.indexOf("-")).length() + 1, userId.length());
        //用户编码
        user.setUserId(userId);
        //sha256加密
        String salt = RandomStringUtils.randomAlphanumeric(20);
        user.setSalt(salt);
        //工号
        user.setNo(stream);
    }

    /**
     * Description:检查公司与选择产品的权限范围是否越权
     *
     * @param
     * @return void
     * @author zhlu
     * @date 2020/1/7 2:35 下午
     */
    private void checkDeptAndProdu(SysUserEntity userEntity) {
        //1.公司编码为空
        if (StringUtils.isEmpty(userEntity.getDeptId())) {
            throw new ServiceException(ServiceCode.COMPANY_USERS);
        }
        //2.未选择产品
        if (CollectionUtils.isEmpty(userEntity.getProductList())) {
            throw new ServiceException(ServiceCode.NO_CORRESPONDING_PRODUCT_SELECTED);
        }
        //3.获取公司与产品的权限功能列表
        List<String> queryDeptAndMenuList = sysMenuService.queryDeptAndMenuList(userEntity.getDeptId(), userEntity.getProductList());
        //4.获取当前选择的角色的权限功能列表
        List<String> queryMenuIdList = sysRoleMenuService.queryMenuIdList(userEntity.getRoleList());
        //5.然后角色权限功能列表和用户选择权限功能列表合并
        queryMenuIdList.addAll(userEntity.getMenuList());
        //6.判断当前用户的权限是否越权
        if (!queryDeptAndMenuList.containsAll(queryMenuIdList)) {
            throw new ServiceException(ServiceCode.UNREASONABLE_CHOICE_OF_PERMISSION_FUNCTION);
        }
    }

    /**
     * Description:检查选择产品的权限范围是否越权
     *
     * @param
     * @return void
     * @author zhlu
     * @date 2020/1/7 2:35 下午
     */
    private void checkProdu(SysUserEntity userEntity) {
        //1.未选择产品
        if (CollectionUtils.isEmpty(userEntity.getProductList())) {
            throw new ServiceException(ServiceCode.NO_CORRESPONDING_PRODUCT_SELECTED);
        }
        //2.根据产品编码。获取当前产品的权限列表
        List<String> queryProductIdList = sysMenuService.queryProductIdList(userEntity.getProductList());
        //3.获取当前选择的角色的权限功能列表
        List<String> queryMenuIdList = sysRoleMenuService.queryMenuIdList(userEntity.getRoleList());
        //4.然后角色权限功能列表和用户选择权限功能列表合并
        queryMenuIdList.addAll(userEntity.getMenuList());
        //6.判断当前用户的权限是否越权
        if (!queryProductIdList.containsAll(queryMenuIdList)) {
            throw new ServiceException(ServiceCode.UNREASONABLE_CHOICE_OF_PERMISSION_FUNCTION);
        }
    }


    @Override
    @Transactional
    public void update(SysUserEntity user) {
        if (StringUtils.isBlank(user.getPassword())) {
            user.setPassword(null);
        } else {
            user.setPassword(new Sha256Hash(user.getPassword(), user.getSalt()).toHex());
        }
        this.updateById(user);

        //检查角色是否越权
//		checkRole(user);

        //保存用户与角色关系
//		sysUserRoleService.saveOrUpdate(user.getUserId(), user.getRoleIdList());
    }

    @Override
    public void deleteBatch(Long[] userId) {
        this.removeByIds(Arrays.asList(userId));
    }

    @Override
    public boolean updatePassword(String userId, String password, String newPassword) {
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setPassword(newPassword);
        return this.update(userEntity,
                new QueryWrapper<SysUserEntity>().eq("user_id", userId).eq("password", password));
    }

    /**
     * Description:检查角色是否越权
     *
     * @param user
     * @return void
     * @author zhlu
     * @date 2020/1/7 2:57 下午
     */
    private void checkRole(SysUserEntity user) {
        List<String> roleProduList = Lists.newArrayList();
        List<String> deptProduList = Lists.newArrayList();
        //判断角色是否越权
        for (String string : user.getRoleList()) {
            SysRoleEntity roleEntity = sysRoleService.queryByRoleId(string);
            //公司编码为空。说明是产品角色
            if (Constant.WHETHER_DEPT == roleEntity.getWhetherDept() &&
                    StringUtils.isEmpty(roleEntity.getDeptId())) {
                roleProduList.add(roleEntity.getProductId());
            } else {
                deptProduList.add(roleEntity.getProductId());
            }
        }
        //产品下角色不合理
        if (!user.getProductList().containsAll(roleProduList)) {
            throw new ServiceException(ServiceCode.UNREASONABLE_ROLE_SELECTION);
        }
//		//公司下角色不合理
//		if(user.getDeptId().contains(deptProduList)){
//
//		}
    }
}